﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using Common.Password;
using EFDataModel.Enums;

namespace EFDataModel
{
    public partial class EFUser : IComparable, IComparable<EFUser>
    {
        #region Static
        /// <summary>
        /// Ermitteln des Users anhand der übergenenen LoginEmail, da diese im System ebenfalls einmalig eingetragen ist.
        /// </summary>
        /// <param name="email">Die Mailadresse für die der User gesucht werden soll</param>
        /// <returns>EFUser Objekt | Null bei einem Fehler</returns>
        public static EFUser GetEFUserByEmail(string email, EFModelContainer efModelContainer)
        {
            //Ermitteln des Users anhand seiner EMail adresse
            var user = (from eUser in efModelContainer.EFBaseMenge.OfType<EFUser>() where eUser.LoginEmail.ToLower() == email.ToLower() select eUser).FirstOrDefault();
            if (user != null)
            {
                return user;
            }

            return null;
        }

        /// <summary>
        /// Die Auflistung der Usertypes die für den User zur Verfügung stehen. Nicht in der DB hinterlegt,
        /// hier handelt es sich um ein festes Enum was bei Bedarf erweitert werden kann für weitere spezielle Rollen
        /// </summary>
        /// <returns>Liste mit den zur Verfügung stehenen UserTypes</returns>
        public static SortedList<EUserTypes, string> UserTypes()
        {
            SortedList<EUserTypes, string> userTypes = new SortedList<EUserTypes, string>();
            userTypes.Add(EUserTypes.Admin, Resources.EFResources.AdminRESX);
            userTypes.Add(EUserTypes.SuperUser, Resources.EFResources.SuperUserRESX);
            userTypes.Add(EUserTypes.Registered, Resources.EFResources.RegisteresRESX);
            userTypes.Add(EUserTypes.Member, Resources.EFResources.MemberRESX);
            userTypes.Add(EUserTypes.ExternalUser, Resources.EFResources.ExternalUserRESX);
            userTypes.Add(EUserTypes.None, Resources.EFResources.NoneUserRESX);

            return userTypes;
        }
        #endregion

        #region Member
        /// <summary>
        /// Liste mit den UserRights
        /// </summary>
        private List<UserRight> _hasUserRights;
        #endregion

        #region Properties
        /// <summary>
        /// Den UserType des aktuellen Users festlegen
        /// </summary>
        public EUserTypes UserType
        {
            get { return (EUserTypes)Enum.Parse(typeof(EUserTypes), UserTypeId.ToString()); }
            set { UserTypeId = (int)value; }
        }
        #endregion

        #region Public Functions
        /// <summary>
        /// Gibt zurück welche Rechte dem aktuellen User zugeordnet sind, inkl. der Vererbung aus den Gruppen.
        /// </summary>
        /// <returns>Liste mit den UserRights</returns>
        public List<UserRight> GetUserRights()
        {
            //Da diese Abfrage oft durchgeführt wird, direkt hier eine Liste erstellen
            if (_hasUserRights == null)
            {
                _hasUserRights = new List<UserRight>();
                //Zuweisen der Rechte die der User hat.
                _hasUserRights = UserRights.ToList();

                //Noch prüfen aus welchen Gruppenzuordnungen der User welche Rechte erbt.
                foreach (UserGroup eUserGroup in UserGroups)
                {
                    foreach (UserRight eUserRight in eUserGroup.UserRights)
                    {
                        if (!_hasUserRights.Contains(eUserRight))
                        {
                            _hasUserRights.Add(eUserRight);
                        }
                    }
                }
            }

            return _hasUserRights;
        }

        /// <summary>
        /// Gibt an ob es sich um einen SuperUser handelt
        /// </summary>
        /// <returns>TRUE->SuperUser/Admin Konto | FALSE->Kein SuperUser/Admin Konto</returns>
        public bool IsAdminOrSuperUser()
        {
            if (IsSuperUser() || IsAdmin())
            {
                return true;
            }

            return false;
        }

        /// <summary>
        /// Gibt an ob es sich um ein Administrator Konto handelt.
        /// </summary>
        /// <returns>TRUE->Administrator Konto | FALSE->Kein Administrator Konto</returns>
        public bool IsAdmin()
        {
            if (UserType == EUserTypes.Admin)
            {
                return true;
            }

            return false;
        }

        /// <summary>
        /// Gibt zurück ob der User ein SuperUser ist.
        /// </summary>
        /// <returns>TRUE->SuperUser Konto | FALSE->Kein SuperUser Konto</returns>
        public bool IsSuperUser()
        {
            if (UserType == EUserTypes.SuperUser)
            {
                return true;
            }

            return false;
        }

        /// <summary>
        /// Vergleicht zwei Nutzer anhand des GetFullName
        /// </summary>
        /// <returns>
        /// Ein Wert, der die relative Reihenfolge der verglichenen Objekte angibt.Der Rückgabewert hat folgende Bedeutung:Wert Bedeutung Kleiner als 0 (null) Dieses Objekt ist kleiner als der <paramref name="other"/>-Parameter.Zero Dieses Objekt ist gleich <paramref name="other"/>. Größer als 0 (null) Dieses Objekt ist größer als <paramref name="other"/>. 
        /// </returns>
        /// <param name="other">Ein Objekt, das mit diesem Objekt verglichen werden soll.</param>
        public int CompareTo(EFUser other)
        {
            return string.Compare(this.GetFullName(), other.GetFullName());
        }

        /// <summary>
        /// Verlgeicht 2 Objekte mit einander, es muss sich bei beiden Objekten trotzdem um einen EFUser handeln.
        /// Beide CompareTo Methoden werden benötigt!!
        /// </summary>
        /// <returns>
        /// Ein Wert, der die relative Reihenfolge der verglichenen Objekte angibt.Der Rückgabewert hat folgende Bedeutung:Wert Bedeutung Kleiner als 0 Diese Instanz ist kleiner als <paramref name="obj"/>. 0 Diese Instanz ist gleich <paramref name="obj"/>. Größer als 0 Diese Instanz ist größer als <paramref name="obj"/>. 
        /// </returns>
        /// <param name="obj">Ein Objekt, das mit dieser Instanz verglichen werden soll. </param><exception cref="T:System.ArgumentException"><paramref name="obj"/> hat nicht denselben Typ wie diese Instanz. </exception><filterpriority>2</filterpriority>
        public int CompareTo(object obj)
        {
            //Prüfen ob das übergenene Objekt auch ein User ist.
            if (obj.GetType() == typeof(EFUser))
            {
                EFUser efUser = (EFUser)obj;
                return string.Compare(this.GetFullName(), efUser.GetFullName());
            }

            throw new NotImplementedException("Es muss ein User übergeben werden!");
        }
        #endregion


    }
}
